package com.njtoyo.taxi.admin.logic.business.driver;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.library.common.OperationRecordHelper;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverCustomMessageEventCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverCustomMessageLinkCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.MemberCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.RideStateState;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.rest.presenter.business.driver.DriverTaxiCompanyPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver.DriverRegisterWrapper;
import com.taxi.entity.common.RestResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

import static com.njtoyo.taxi.admin.mapper.master.enums.DriverRegistrationInfoSate.abolish;
import static java.util.stream.Collectors.toList;

@Service
@Slf4j
public class DriverLogic {

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private TaxiMapper taxiMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private PrimaryCachePutter primaryCachePutter;
    @Autowired
    private DriverCustomMessageMapper driverCustomMessageMapper;

    @Autowired
    private OperationRecordHelper operationRecordHelper;

    @Autowired
    private DriverAutomaticOpenTimeLogMapper driverAutomaticOpenTimeLogMapper;

    @Autowired
    private DriverServiceLogMapper driverServiceLogMapper;

    @Autowired
    private DriverWithdrawMapper driverWithdrawMapper;
    @Autowired
    private DriverWithdrawHistoryMapper driverWithdrawHistoryMapper;

    @Autowired
    private RideMapper rideMapper;

    @Autowired
    private SimpleCallRideMapper simpleCallRideMapper;

    @Autowired
    private RecommendationMapper recommendationMapper;

    @Autowired
    private DriverFlowLogMapper driverFlowLogMapper;

    @Autowired
    private DriverRechargeMapper driverRechargeMapper;

    @Autowired
    private DriverBankingMapper driverBankingMapper;

    @Autowired
    private MessageDriverDeliveryMapper messageDriverDeliveryMapper;

    @Autowired
    private DriverAccountMapper driverAccountMapper;

    @Autowired
    private DriverRegistrationInfoMapper driverRegistrationInfoMapper;

    @Autowired
    private DriverExtraInformationMapper driverExtraInformationMapper;


    @Transactional
    public Driver register(DriverRegisterWrapper wrapper) {
        // 姓名
        if (Objects.isNull(wrapper.getName())) {
            throw new RuntimeException("姓名不能为空");
        }
        // 判断手机号
        if (Objects.isNull(wrapper.getMobileNumber()) || !Pattern.matches("^1[0-9]{10}$", wrapper.getMobileNumber())) {
            throw new RuntimeException("手机号格式不正确");
        }
        // 判断车牌
        if (Objects.isNull(wrapper.getPlateNumber()) || !Pattern.matches("[测京津晋冀蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新][A-Za-z0-9]+", wrapper.getPlateNumber())) {
            throw new RuntimeException("车牌号格式不正确");
        }
        // 手机号是否重复
        QueryWrapper<Driver> driverWrapper = new QueryWrapper<>();
        driverWrapper.eq("mobile_number", wrapper.getMobileNumber());
        if (driverMapper.selectCount(driverWrapper) > 0) {
            throw new RuntimeException("号码已存在");
        }
        // 车俩信息
        QueryWrapper<Taxi> taxiWrapper = new QueryWrapper<>();
        taxiWrapper.eq("plate_number", wrapper.getPlateNumber());
        Taxi taxi = taxiMapper.selectOne(taxiWrapper);
        if (Objects.isNull(taxi)) {
            throw new RuntimeException("车俩不存在");
        }
        if (taxi.getIsScrapped()) {
            throw new RuntimeException("车俩已经报废");
        }
        // 公司信息
        Company company = companyMapper.selectById(taxi.getCompanyId());
        if (Objects.isNull(company)) {
            throw new RuntimeException("车俩对应公司不存在");
        }

        // 判断身份证号长度
        if (Objects.nonNull(wrapper.getIdentityNumber()) && wrapper.getIdentityNumber().length() != 18) {
            throw new RuntimeException("身份证号格式不正确");
        }
        DriverExtraInformation driverExtraInformation = driverExtraInformationMapper.selectOne(Wrappers.<DriverExtraInformation>lambdaQuery()
                .eq(DriverExtraInformation::getIdentityNumber, wrapper.getIdentityNumber()));
        if (ObjectUtil.isNotNull(driverExtraInformation)) {
            throw new RuntimeException("身份证号已存在,不能重复添加！");
        }

        // 判断是否有额外信息
        boolean hasExtra = Objects.nonNull(wrapper.getIdentityNumber()) || Objects.nonNull(wrapper.getServiceNumber()) || Objects.nonNull(wrapper.getRoadTransportNumber()) || Objects.nonNull(wrapper.getQualificationCertificateNumber());

        // 添加司机信息
        Driver driver = new Driver();
        driver.setName(wrapper.getName())
                .setMobileNumber(StrUtil.trim(wrapper.getMobileNumber()))
                .setPassword(SecureUtil.md5(wrapper.getMobileNumber().substring(5) + "@yd"))
                .setAvatarUrl("https://store.jjtoyo.com/driver/driver-head.png")
                .setLocateCityId(wrapper.getCityId())
                .setDriverRegionId(company.getDriverRegionId())
                .setCantonId(company.getCantonId())
                .setIsActive(true)
                .setTaxiId(taxi.getId());
        driverMapper.insert(driver);
        log.info("插入司机信息 {}", driver);
        // 添加会员信息
        Member member = new Member();
        member.setCategory(MemberCategory.driver)
                .setRefId(driver.getId());
        memberMapper.insert(member);
        log.info("插入会员信息 {}", member);
        // 司机消息
        DriverCustomMessage message = new DriverCustomMessage();
        message.setDriverId(driver.getId())
                .setContent("欢迎使用巡网融合出行平台，优质派单、安全出行。")
                .setIsPlainText(true)
                .setLinkCategory(DriverCustomMessageLinkCategory.self)
                .setEventCategory(DriverCustomMessageEventCategory.system)
                .setIsRead(false);
        driverCustomMessageMapper.insert(message);
        log.info("插入司机消息 {}", message);

        // 如果存在额外信息，则插入
        if (hasExtra) {
            DriverExtraInformation extra = new DriverExtraInformation();
            extra.setDriverId(driver.getId());

            if (ObjectUtil.isNotEmpty(wrapper.getIdentityNumber())) {
                extra.setIdentityNumber(StrUtil.trim(wrapper.getIdentityNumber()));
            }

            if (ObjectUtil.isNotEmpty(wrapper.getServiceNumber())) {
                extra.setServiceNumber(StrUtil.trim(wrapper.getServiceNumber()));
            }

            if (ObjectUtil.isNotEmpty(wrapper.getRoadTransportNumber())) {
                extra.setRoadTransportNumber(StrUtil.trim(wrapper.getRoadTransportNumber()));
            }

            if (ObjectUtil.isNotEmpty(wrapper.getQualificationCertificateNumber())) {
                extra.setQualificationCertificateNumber(StrUtil.trim(wrapper.getQualificationCertificateNumber()));
            }

            driverExtraInformationMapper.insert(extra);
            log.info("插入司机额外消息 {}", extra);
        }

        return driver;
    }

    /**
     * 单个司机换车牌
     *
     * @param
     * @param
     * @return
     */
    public Driver switchTaxi(Long id, Long taxiId) {
        Taxi taxi = taxiMapper.selectById(taxiId);
        Driver driver = driverMapper.selectById(id);
        if (ObjectUtils.isEmpty(driver)) {
            throw new RuntimeException("司机不存在");
        }
        if (ObjectUtils.isEmpty(taxi)) {
            throw new RuntimeException("车辆不存在");
        }
        if (taxi.getIsScrapped()) {
            throw new RuntimeException("车辆已经报废");
        }
        if (taxi.getId().equals(driver.getTaxiId())) {
            throw new RuntimeException("已经绑定至该车辆");
        }
        DriverTaxiCompanyPresenter driverTaxiCompanyPresenter = taxiMapper.selectTaxiCompanyId(taxi.getId());
        if (ObjectUtils.isEmpty(driverTaxiCompanyPresenter)) {
            throw new RuntimeException("车辆区域运营暂无");
        }
        Long cantonId = driverTaxiCompanyPresenter.getCantonId();
        Long driverRegionId = driverTaxiCompanyPresenter.getDriverRegionId();
        new LambdaUpdateChainWrapper<>(driverMapper)
                .eq(Driver::getId, driver.getId())
                .set(Driver::getTaxiId, taxiId)
                .set(Driver::getDriverRegionId, driverRegionId)
                .set(Driver::getCantonId, cantonId)
                .update();
        primaryCachePutter.deleteDriverCacheById(id);
        return driver;
    }

    /**
     * 批量司机换车牌
     *
     * @param
     * @param
     * @return
     */
    public Driver switchTaxi(Long id, String plateNumber) {
        //通过车牌查询车辆的ID
        QueryWrapper<Taxi> wrapper = new QueryWrapper<>();
        wrapper.select("id", "plate_number", "is_scrapped");
        wrapper.eq("plate_number", plateNumber);
        Taxi taxi = taxiMapper.selectOne(wrapper);
        if (ObjectUtils.isEmpty(taxi)) {
            throw new RuntimeException("车辆不存在");
        }
        if (taxi.getIsScrapped()) {
            throw new RuntimeException("车辆已经报废");
        }
        Driver driver = switchTaxi(id, taxi.getId());
        operationRecordHelper.addBusinessLog(String.format("将司机 [%d] 的车牌号换成了 %s ", id, plateNumber));
        return driver;
    }

    @Transactional
    public void setOffline(Driver driver) {
        // 获取车俩信息
        Taxi taxi = taxiMapper.selectById(driver.getTaxiId());
        // 获取绑定司机信息
        QueryWrapper<Driver> queryWrapper = new QueryWrapper<Driver>()
                .eq("taxi_id", driver.getTaxiId())
                .select("id");
        List<Map<String, Object>> mapList = driverMapper.selectMaps(queryWrapper);
        List<Long> driverIds = mapList.stream().map(o -> (Long) o.get("id")).collect(toList());
        new LambdaUpdateChainWrapper<>(taxiMapper)
                .eq(Taxi::getId, taxi.getId())
                .set(Taxi::getIsAvailable, false)
                .set(Taxi::getUpdatedAt, new Date())
                .update();
        new LambdaUpdateChainWrapper<>(driverMapper)
                .in(Driver::getId, driverIds)
                .set(Driver::getInService, false)
                .set(Driver::getUpdatedAt, new Date())
                .update();
        // 清除缓存
        for (Long driverId : driverIds) {
            primaryCachePutter.deleteDriverCacheById(driverId);
        }
    }

    @Transactional
    public Long closeDriverAutomatic(Ride ride, DateTime automaticOpenTime) {
        // 新增关闭日志
        DriverAutomaticOpenTimeLog log = new DriverAutomaticOpenTimeLog();
        log.setDriverId(ride.getDriverId());
        log.setRideId(ride.getId());
        log.setAutomaticOpenTime(automaticOpenTime);
        driverAutomaticOpenTimeLogMapper.insert(log);

        // 关闭司机自动抢单
        new LambdaUpdateChainWrapper<>(driverMapper)
                .eq(Driver::getId, ride.getDriverId())
                .set(Driver::getIsAutomatic, false)
                .set(Driver::getUpdatedAt, new Date())
                .update();

        return log.getId();
    }

    /**
     * 删除司机
     *
     * @param id
     * @return
     */
    @Transactional
    public RestResult deleteDriver(Long id) {
        driverFlowLogMapper.delete(Wrappers.<DriverFlowLog>lambdaQuery().eq(DriverFlowLog::getDriverId, id));
        List<DriverWithdraw> driverWithdraws = driverWithdrawMapper.selectList(Wrappers.<DriverWithdraw>lambdaQuery().eq(DriverWithdraw::getDriverId, id));
        for (DriverWithdraw driverWithdraw : driverWithdraws) {
            driverWithdrawMapper.deleteById(driverWithdraw.getId());
            driverWithdrawHistoryMapper.delete(Wrappers.<DriverWithdrawHistory>lambdaQuery()
                    .eq(DriverWithdrawHistory::getDriverWithdrawId, driverWithdraw.getId()));
        }
        //删除绑定银行卡
        QueryWrapper<DriverBanking> driverBankingWrapper = new QueryWrapper<>();
        driverBankingWrapper.eq("driver_id", id);
        driverBankingMapper.delete(driverBankingWrapper);
        //        删除消息记录
        QueryWrapper<MessageDriverDelivery> driverDeliveryWrapper = new QueryWrapper<>();
        driverDeliveryWrapper.eq("driver_id", id);
        messageDriverDeliveryMapper.delete(driverDeliveryWrapper);
        QueryWrapper<DriverCustomMessage> driverCustomMessageWrapper = new QueryWrapper<>();
        driverCustomMessageWrapper.eq("driver_id", id);
        driverCustomMessageMapper.delete(driverCustomMessageWrapper);
        //        删除会员信息
        QueryWrapper<Member> memberWrapper = new QueryWrapper<>();
        memberWrapper.eq("ref_id", id);
        memberWrapper.eq("category", 0);
        memberMapper.delete(memberWrapper);
        //        删除司机账户
        QueryWrapper<DriverAccount> driverAccountWrapper = new QueryWrapper<>();
        driverAccountWrapper.eq("driver_id", id);
        driverAccountMapper.delete(driverAccountWrapper);
        //        删除司机信息
        driverMapper.deleteById(id);
        primaryCachePutter.deleteDriverCacheById(id);
        //司机扩展信息删除
        QueryWrapper<DriverExtraInformation> driverExtraInformationQueryWrapper = new QueryWrapper<>();
        driverExtraInformationQueryWrapper.eq("driver_id", id);
        driverExtraInformationMapper.delete(driverExtraInformationQueryWrapper);
        return RestResult.success();
    }

    public Driver selectDriverNameMobileById(Long driverId) {
        return new LambdaQueryChainWrapper<>(driverMapper)
                .select(Driver::getId, Driver::getName, Driver::getMobileNumber)
                .eq(Driver::getId, driverId)
                .one();
    }

    public List<Driver> selectListByIds(List<Long> ids) {
        return new LambdaQueryChainWrapper<>(driverMapper)
                .in(Driver::getId, ids)
                .list();
    }


    /**
     * 查询司机余额
     *
     * @param driverId
     * @return
     */

    public BigDecimal getDriverBalance(Long driverId) {
        BigDecimal balance = driverMapper.getDriverBalance(driverId);
        return ObjectUtil.isNull(balance) ? BigDecimal.ZERO : balance;
    }


    /**
     * 是否有未完成订单 Ture:没有未完成订单 false:有未完成订单
     *
     * @param driverId
     * @return
     */
    public boolean isNotFinishOrder(Long driverId) {
        List<Ride> rides = rideMapper.selectList(Wrappers.<Ride>lambdaQuery()
                .eq(Ride::getDriverId, driverId)
                .in(Ride::getState, Arrays.asList(RideStateState.waiting, RideStateState.contracted, RideStateState.pickuping, RideStateState.started, RideStateState.inarea)));
        if (CollUtil.isNotEmpty(rides)) {
            return false;
        }
        List<SimpleCallRide> simpleCallRides = simpleCallRideMapper.selectList(Wrappers.<SimpleCallRide>lambdaQuery()
                .eq(SimpleCallRide::getDriverId, driverId)
                .eq(SimpleCallRide::getIsCancel, false)
                .eq(SimpleCallRide::getIsFinished, false)
                .in(SimpleCallRide::getState, Arrays.asList(com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState.pickUp, com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState.inArea, SimpleCallRideState.start)));

        if (CollUtil.isNotEmpty(simpleCallRides)) {
            return false;
        }
        return true;
    }
}
